package values

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"time"
	"unsafe"
)

// ToMapSlice 转换目标为 map[K][]V, 如果转换失败, 则返回空的 map[K][]V
//   - K: map key 的类型 TypeBase
//   - V: map val 的类型 []TypeBase
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToMapSlice[K TypeBase, V TypeBase](v any) map[K][]V {
	if v == nil {
		return map[K][]V{}
	}
	to, _ := ToMapSliceE[K, V](v)
	return to
}

// ToMapSliceD 转换目标为 map[K][]V, 如果转换失败, 则返回defaultVal指定的map
//   - K: map key 的类型 TypeBase
//   - V: map val 的类型 []TypeBase
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToMapSliceD[K TypeBase, V TypeBase](v any, defaultVal map[K][]V) map[K][]V {
	if v == nil {
		return defaultVal
	}
	if to, err := ToMapSliceE[K, V](v); err == nil {
		return to
	}
	return defaultVal
}

// ToMapSliceE 转换目标为 map[K][]V, 如果转换失败, 则返回空的 map[K][]V 和错误信息
//   - K: map key 的类型 TypeBase
//   - V: map val 的类型 []TypeBase
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func ToMapSliceE[K TypeBase, V TypeBase](v any) (map[K][]V, error) {
	return _toMapSliceE[K, V](UnderefVal(v))
}

// _toMapSliceE 转换目标为 map[K][]V, 如果转换失败, 则返回空的 map[K][]V 和错误信息
//   - 待转换目标为已经UnderefVal处理的参数
func _toMapSliceE[K TypeBase, V TypeBase](v any) (map[K][]V, error) {
	toVal := map[K][]V{}
	if v == nil {
		return toVal, errors.New("ToMapSliceE: nil pointer not support")
	}
	// 先通过断言判断待转换值是否为 map[K][]V / map[K]any / map[K][]any / map[any]any / map[any][]any  类型
	switch vs := v.(type) {
	case map[K][]V:
		return _toMapSliceAppend(vs)
	case map[K]any:
		return _toMapSliceAnyV[K, V](vs)
	case map[K][]any:
		if len(vs) == 0 {
			return toVal, nil
		}
		vsAny := make(map[K]any, len(vs))
		for k, v := range vs {
			vsAny[k] = v
		}
		return _toMapSliceAnyV[K, V](vsAny)
	case map[any]any:
		return _toMapSliceAnyKV[K, V](vs)
	case map[any][]any:
		if len(vs) == 0 {
			return toVal, nil
		}
		vsAny := make(map[any]any, len(vs))
		for k, v := range vs {
			vsAny[k] = v
		}
		return _toMapSliceAnyKV[K, V](vsAny)
	case []byte:
		if json.Valid(vs) {
			var toAny map[K]any
			if err := json.Unmarshal(vs, &toAny); err == nil {
				return _toMapSliceE[K, V](toAny)
			} else {
				return toVal, fmt.Errorf("ToMapSliceE: []byte to map[K][]V type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToMapSliceE: []byte to map[K][]V type not support")
	case string:
		if vs != "" && strings.HasPrefix(vs, "{") && strings.HasSuffix(vs, "}") && json.Valid([]byte(vs)) {
			var toAny map[K]any
			if err := json.Unmarshal([]byte(vs), &toAny); err == nil {
				return _toMapSliceE[K, V](toAny)
			} else {
				return toVal, fmt.Errorf("ToMapSliceE: string to map[K][]V type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToMapSliceE: string to map[K][]V type not support")
	case bool,
		int, int8, int16, int32, int64,
		uint, uint8, uint16, uint32, uint64, uintptr,
		float32, float64,
		complex64, complex128,
		time.Time, time.Duration, time.Location, time.Month, time.Weekday, time.Ticker, time.Timer,
		struct{}, chan any, func(), unsafe.Pointer,
		bytes.Buffer, strings.Builder,
		reflect.Type, reflect.Value, reflect.Kind,
		sync.Mutex, sync.RWMutex, sync.Cond, sync.Once, sync.Pool, sync.WaitGroup, sync.Locker,
		error,
		json.Number:
		// 如果待转换值是Golang 常用的基本类型, 则直接返回错误信息
		return toVal, errors.New("ToMapSliceE: basicType to map[K][]V type not support")
	}

	// 通过断言判断待转换值是否为 map[X]X 类型
	if toVal, err, next := _toMapSliceWithKey[K, V, string](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, int](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, uint](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, int64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, uint64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, int32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, uint32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, int16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, uint16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, int8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, uint8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, float32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, float64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, float64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, time.Time](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, time.Duration](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, time.Month](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, time.Weekday](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapSliceWithKey[K, V, bool](v); !next {
		return toVal, err
	}
	return toVal, fmt.Errorf("ToMapSliceE: type of %T to type of map[K][]V  not support", v)
}
func _toMapSliceAppend[K TypeBase, V TypeBase](vs map[K][]V) (map[K][]V, error) {
	if vs == nil {
		return map[K][]V{}, errors.New("ToMapSliceE: nil pointer not support")
	}
	if len(vs) == 0 {
		return map[K][]V{}, nil
	}
	toVal := make(map[K][]V, len(vs))
	for key, val := range vs {
		toVal[key] = val
	}
	return toVal, nil
}
func _toMapSliceAnyV[K TypeBase, V TypeBase](vs map[K]any) (map[K][]V, error) {
	if vs == nil {
		return map[K][]V{}, errors.New("ToMapSliceE: nil pointer not support")
	}
	if len(vs) == 0 {
		return map[K][]V{}, nil
	}
	toMap := make(map[K][]V, len(vs))

	for key, item := range vs {
		if item == nil {
			return map[K][]V{}, errors.New("ToMapSliceE: nil pointer not support")
		}
		if val, ok := item.([]V); ok {
			toMap[key] = val
			continue
		}
		if val, err := ToSliceAsE[V](item); err != nil {
			return map[K][]V{}, fmt.Errorf("ToMapSliceE: %s", err.Error())
		} else {
			toMap[key] = val
		}
	}
	return toMap, nil
}
func _toMapSliceAnyKV[K TypeBase, V TypeBase](vs map[any]any) (map[K][]V, error) {
	if vs == nil {
		return map[K][]V{}, errors.New("ToMapSliceE: nil pointer not support")
	}
	if len(vs) == 0 {
		return map[K][]V{}, nil
	}
	toVal := make(map[K][]V, len(vs))
	var (
		toK K
		toV []V
	)
	for key, item := range vs {
		if val, ok := key.(K); ok {
			toK = val
		} else if val, err := ToBaseE[K](key); err == nil {
			toK = val
		} else {
			return map[K][]V{}, fmt.Errorf("ToMapSliceE: K[%#v] to type of %T, error:%s", key, toK, err.Error())
		}
		if val, ok := item.([]V); ok {
			toV = val
		} else if val, err := ToSliceAsE[V](item); err == nil {
			toV = val
		} else {
			return map[K][]V{}, fmt.Errorf("ToMapSliceE: V[%#v] to type of %T,, error:%s", item, toV, err.Error())
		}
		toVal[toK] = toV
	}
	return toVal, nil
}
func _toMapSliceWithKey[K TypeBase, V TypeBase, Key TypeBase](v any) (map[K][]V, error, bool) {
	switch vs := v.(type) {
	default:
		return map[K][]V{}, nil, true // Next "true" To continue
	case map[Key][]V:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]any:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]string:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]bool:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]int:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]int8:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]int16:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]int32:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]int64:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]uint:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]uint8:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]uint16:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]uint32:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]uint64:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]float32:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]float64:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]time.Time:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]time.Duration:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]time.Weekday:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]time.Month:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]json.Number:
		return _toMapSliceWithLoop[K, V](vs)
	case map[Key][]error:
		return _toMapSliceWithLoop[K, V](vs)
	}
}
func _toMapSliceWithLoop[K TypeBase, V TypeBase, vsK TypeBase, vsV any](vs map[vsK][]vsV) (map[K][]V, error, bool) {
	if vs == nil {
		return map[K][]V{}, errors.New("ToMapSliceE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return map[K][]V{}, nil, false // Next "false" To Break
	}
	toVal := make(map[K][]V, len(vs))
	var (
		toK K
		toV []V
	)
	for key, item := range vs {
		if val, ok := any(key).(K); ok {
			toK = val
		} else if val, err := ToBaseE[K](key); err == nil {
			toK = val
		} else {
			return map[K][]V{}, fmt.Errorf("ToMapSliceE: K[%#v] to type of %T, error:%s", key, toK, err.Error()), false // Next "false" To Break
		}
		if val, ok := any(item).([]V); ok {
			toV = val
		} else if val, err := ToSliceAsE[V](item); err == nil {
			toV = val
		} else {
			return map[K][]V{}, fmt.Errorf("ToMapSliceE: V[%#v] to type of %T,, error:%s", item, toV, err.Error()), false // Next "false" To Break
		}
		toVal[toK] = toV
	}
	return toVal, nil, false // Next "false" To Break
}
